package cn.yuan.xiaoyu.testmodule.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.support.annotation.Nullable;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.animation.FastOutLinearInInterpolator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.OverScroller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import cn.yuan.xiaoyu.commonmodule.utils.ListUtils;
import cn.yuan.xiaoyu.testmodule.bean.DayCalendar;
import cn.yuan.xiaoyu.testmodule.bean.DayCalendarBean;
import cn.yuan.xiaoyu.wangmodule.utils.DataUtil;

/**
 * Created by yukuoyuan on 2017/5/5.
 * 这是一个自定义的日历的界面
 */
public class DayCalendarView extends View {

    private int mScaledTouchSlop = 0;
    /**
     * 当前的原点位置
     */
    private PointF mCurrentOrigin = new PointF(0f, 0f);
    private int mMinimumFlingVelocity;
    private float mWidthPerDoctor;
    /**
     * 时间字体的大小
     */
    private float mTimeTextSize = 22;
    /**
     * 头布局字体的画笔
     */
    private Paint mHeaderTextPaint;
    /**
     * 头布局字体的大小28px
     */
    private float mHeaderTextSize;
    /**
     * 所有的时间刻度的集合
     */
    private List<String> timelist;

    /**
     * 定义用户行为的几个状态
     */
    private enum Direction {
        NONE, LEFT, RIGHT, VERTICAL
    }

    /**
     * 默认用户的滑动行为
     */
    private Direction mCurrentScrollDirection = Direction.NONE;
    /**
     * 默认用户突然的行为
     */
    private Direction mCurrentFlingDirection = Direction.NONE;

    /**
     * 医生的数量
     */
    private int mDoctorSize = 20;
    /**
     * 全局的上下文
     */
    private Context mContext;
    /**
     * 这是绘制左边时间的画笔
     */
    private Paint mTimeTextPaint;
    /**
     * 绘制时间刻度的颜色
     */
    private int mTimeTextColor = Color.rgb(102, 102, 102);
    /**
     * 时间刻度的高度
     */
    private float mTimeTextHeight = 70f;
    /**
     * 时间刻度的宽度
     */
    private float mTimeTextWidth = 84f;
    /**
     * 默认头部的高度
     */
    private float mHeaderHeight = 84f;
    /**
     * 头部内容的pading值
     */
    private float mHeaderRowPadding = 28f;
    /**
     * 时间的高度
     */
    private float mHourHeight = 70f;
    /**
     * 滑动的时间
     */
    private int mScrollDuration = 250;
    /**
     * 数据源
     */
    private DayCalendarBean dayCalendarBean;
    /**
     * 滑动监听处理
     */
    private final GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {
        /**
         * 长按调用的方法
         * @param e
         */
        @Override
        public void onLongPress(MotionEvent e) {
            super.onLongPress(e);
        }

        /**
         * 手指按下屏幕并拖动滑动
         * @param e1
         * @param e2
         * @param distanceX
         * @param distanceY
         * @return
         */
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            /**
             * 初始化选择的滑动的状态
             */
            switch (mCurrentScrollDirection) {
                case NONE: {
                    //只允许在一个方向滚动。
                    if (Math.abs(distanceX) > Math.abs(distanceY)) {
                        if (distanceX > 0) {
                            mCurrentScrollDirection = Direction.LEFT;
                        } else {
                            mCurrentScrollDirection = Direction.RIGHT;
                        }
                    } else {
                        mCurrentScrollDirection = Direction.VERTICAL;
                    }
                    break;
                }
                case LEFT: {
                    // 改变方向，如果有足够的变化。
                    if (Math.abs(distanceX) > Math.abs(distanceY) && (distanceX < -mScaledTouchSlop)) {
                        mCurrentScrollDirection = Direction.RIGHT;
                    }
                    break;
                }
                case RIGHT: {
                    //改变方向，如果有足够的变化。
                    if (Math.abs(distanceX) > Math.abs(distanceY) && (distanceX > mScaledTouchSlop)) {
                        mCurrentScrollDirection = Direction.LEFT;
                    }
                    break;
                }
            }
            // 计算滚动后的新原点。
            switch (mCurrentScrollDirection) {
                case LEFT:
                case RIGHT:
                    if (mDoctorSize > 4) {
                        mCurrentOrigin.x -= distanceX;
                        ViewCompat.postInvalidateOnAnimation(DayCalendarView.this);
                    }
                    break;
                case VERTICAL:
                    mCurrentOrigin.y -= distanceY;
                    ViewCompat.postInvalidateOnAnimation(DayCalendarView.this);
                    break;
            }
            return true;
        }

        /**
         * 用户按下,快速滑动后松开
         * @param e1
         * @param e2
         * @param velocityX
         * @param velocityY
         * @return
         */
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            mScroller.forceFinished(true);
            mCurrentFlingDirection = mCurrentScrollDirection;
            switch (mCurrentFlingDirection) {
                case LEFT:
                case RIGHT:
                    if (mDoctorSize > 4) {
                        mScroller.fling((int) mCurrentOrigin.x,//滚动起始点X坐标
                                (int) mCurrentOrigin.y,//滚动起始点Y坐标
                                (int) (velocityX),//当滑动屏幕时X方向初速度，以每秒像素数计算
                                0,//当滑动屏幕时Y方向初速度，以每秒像计算
                                (int) -(mWidthPerDoctor * mDoctorSize + mHeaderHeight - getWidth()),
                                0,//X方向的最大值，scroller不会滚过此点
                                (int) -(mHourHeight * 48 + mHeaderHeight + mHeaderRowPadding * 2 + mTimeTextHeight / 2 - getHeight()),// Y方向的最小值，scroller不会滚过此点
                                0);//Y方向的最大值，scroller不会滚过此点。
                    }
                    break;
                case VERTICAL:
                    mScroller.fling((int) mCurrentOrigin.x,
                            (int) mCurrentOrigin.y,
                            0,
                            (int) velocityY,
                            (int) -(mWidthPerDoctor * mDoctorSize + mHeaderHeight - getWidth()),
                            0,
//                            (int) -(mHourHeight * 48 + mHeaderHeight + mHeaderRowPadding * 2 + mTimeTextHeight / 2 - getHeight()),
                            (int) -(mHourHeight * 49 + mHeaderHeight - getHeight()),
                            0);
                    break;
            }
            ViewCompat.postInvalidateOnAnimation(DayCalendarView.this);
            return true;
        }

        /**
         * 按下屏幕
         * @param e
         * @return
         */
        @Override
        public boolean onDown(MotionEvent e) {
            goToNearestOrigin();
            return true;
        }


        /**
         * 严格的单击行为
         * @param e
         * @return
         */
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            return super.onSingleTapConfirmed(e);
        }


    };
    private GestureDetectorCompat mGestureDetector;
    private OverScroller mScroller;

    public DayCalendarView(Context context) {
        this(context, null);
    }

    public DayCalendarView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DayCalendarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        initView();
    }

    /**
     * 初始化界面
     */
    private void initView() {
        /**
         * 滑动的初始化
         */
        mGestureDetector = new GestureDetectorCompat(mContext, mGestureListener);
        mScroller = new OverScroller(mContext, new FastOutLinearInInterpolator());
        mScaledTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
        mMinimumFlingVelocity = ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity();

        /**
         * 初始化左边时间的画笔22px像素颜色666
         */
        mTimeTextPaint = new Paint();
        mTimeTextPaint.setTextSize(mTimeTextSize);
        mTimeTextPaint.setStyle(Paint.Style.FILL);
        mTimeTextPaint.setColor(mTimeTextColor);
        /**
         * 初始化头部的画笔
         */
        mHeaderTextPaint = new Paint();
        mHeaderTextPaint.setTextSize(mHeaderTextSize);
        mHeaderTextPaint.setStyle(Paint.Style.FILL);
        mHeaderTextPaint.setColor(Color.rgb(255, 192, 203));

    }

    /**
     * 绘制方法
     *
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /**
         * 绘制时间刻度
         */
        drawTimeColumnAndAxes(canvas);
        /**
         * 绘制头部下边的事件
         */
        drawHeaderRowAndEvents(canvas);

    }

    /**
     * 绘制头部和下边的事件
     *
     * @param canvas
     */
    private void drawHeaderRowAndEvents(Canvas canvas) {
        /**
         *重置我们的y方向
         */
        if (mCurrentOrigin.y > 0) {
            mCurrentOrigin.y = 0;
        }
        if (mCurrentOrigin.y < getHeight() - mHourHeight * 48 - mHeaderHeight - mHeaderRowPadding * 2 - mTimeTextHeight / 2)
            mCurrentOrigin.y = getHeight() - mHourHeight * 48 - mHeaderHeight - mHeaderRowPadding * 2 - mTimeTextHeight / 2;
        //if (mCurrentOrigin.x < getWidth() - mWidthPerDoctor * mDoctorSize + mHeaderHeight)
        //  mCurrentOrigin.x = getWidth() - mWidthPerDoctor * mDoctorSize + mHeaderHeight;

        /**
         *左右的偏移量
         */
        int leftDaysWithGaps = (int) -(Math.ceil(mCurrentOrigin.x / (mWidthPerDoctor)));
        Log.d("左边偏移量", leftDaysWithGaps + "");
        /**
         * 重置我们的x方向值
         */
        if (leftDaysWithGaps < 0) {
            mCurrentOrigin.x = 0;
        }

        /**
         * 计算开始的位置
         */
        float startFromPixel = mCurrentOrigin.x + (mWidthPerDoctor) * leftDaysWithGaps +
                mWidthPerDoctor;
        Log.d("头布局字体的位置", startFromPixel + "****");
        /**
         * 绘制所有的区域文字
         */
        drawAllEventText(canvas);
    }

    /**
     * 绘制所有区域的内容
     *
     * @param canvas
     */
    private void drawAllEventText(Canvas canvas) {
        if (null == dayCalendarBean) {
            return;
        }
        /**
         * 没有医生跳出界面
         */
        if (ListUtils.isEmpty(dayCalendarBean.Items)) {
            return;
        }
        /**
         * 判断矩形显示的y轴
         */
        for (int i = 0; i < dayCalendarBean.Items.size(); i++) {
            float leftx = mTimeTextWidth + mWidthPerDoctor * i + mCurrentOrigin.x;
            /**
             * 假如当前医生没有预约的人那么进入下个医生中
             */
            if (ListUtils.isEmpty(dayCalendarBean.Items.get(i).List)) {
                continue;
            }
            for (DayCalendar dayCalendar : dayCalendarBean.Items.get(i).List) {
                float top = getTopAndBottomHour(DataUtil.getHourMinutes(dayCalendar.StartTime));
                float bottom = getTopAndBottomHour(DataUtil.getHourMinutes(dayCalendar.EndTime));
                canvas.drawRect(leftx, top, leftx + mWidthPerDoctor, bottom, mHeaderTextPaint);
                canvas.drawText(dayCalendar.PatientName, leftx + mWidthPerDoctor / 2, top + (bottom - top) / 2, mTimeTextPaint);
            }
        }
    }

    /**
     * 根据时间获取距离顶部的距离
     *
     * @param time
     * @return
     */
    private float getTopAndBottomHour(String time) {
        float top = 0f;
        for (int i = 0; i < timelist.size(); i++) {
            if (timelist.get(i).equals(time)) {
                top = mTimeTextWidth + mTimeTextHeight * i + mTimeTextHeight + mCurrentOrigin.y;
            }
        }
        return top;
    }

    /**
     * 滑动调用的方法
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean consume = mGestureDetector.onTouchEvent(event);
        /**
         * 如果当前的行为是离开,并且猛然没有滑动行为
         */
        if (event.getAction() == MotionEvent.ACTION_UP && mCurrentFlingDirection == Direction.NONE) {
            /**
             * 如果滚动的行为是像左或者向右滑动,就滚动界面
             */
            if (mCurrentScrollDirection == Direction.RIGHT || mCurrentScrollDirection == Direction.LEFT) {
                goToNearestOrigin();
            }
            /**
             * 滚动完之后,把选中的行为重置
             */
            mCurrentScrollDirection = Direction.NONE;
        }
        return consume;
    }

    /**
     * 计算滑动
     */
    @Override
    public void computeScroll() {
        super.computeScroll();
        /**
         * 判断滑动是否完成
         */
        if (mScroller.isFinished()) {
            if (mCurrentFlingDirection != Direction.NONE) {
                // 猛然的行为停止后
                goToNearestOrigin();
            }
        } else {
            if (mCurrentFlingDirection != Direction.NONE && mScroller.getCurrVelocity() <= mMinimumFlingVelocity) {
                goToNearestOrigin();
            } else if (mScroller.computeScrollOffset()) {
                mCurrentOrigin.y = mScroller.getCurrY();
                mCurrentOrigin.x = mScroller.getCurrX();
                ViewCompat.postInvalidateOnAnimation(this);
            }
        }
    }

    /**
     * 绘制时间刻度喝轴
     *
     * @param canvas
     */
    private void drawTimeColumnAndAxes(Canvas canvas) {
        /**
         * 绘制时间刻度右边的线
         */
        Paint TimeRightLinePaint = new Paint();
        TimeRightLinePaint.setColor(Color.parseColor("#dbdbdb"));
        //第一条横线
        canvas.drawLine(0, mTimeTextWidth + mCurrentOrigin.y, getWidth(), mTimeTextWidth + 1 + mCurrentOrigin.y, TimeRightLinePaint);
        /**
         * 每天的宽度
         */
        if (mDoctorSize < 4) {
            mWidthPerDoctor = (getWidth() - mTimeTextWidth) / mDoctorSize;
        } else {
            mWidthPerDoctor = (getWidth() - mTimeTextWidth) / 4;
        }
        Log.d("屏幕的宽度", getWidth() + "***" + mWidthPerDoctor);
        /**
         * 绘制竖线
         */
        for (int i = 0; i <= mDoctorSize; i++) {
            float left = mTimeTextWidth + mWidthPerDoctor * i;
            canvas.drawLine(left + mCurrentOrigin.x, 0, left + mCurrentOrigin.x + 1, 48 * mHourHeight + mHeaderHeight, TimeRightLinePaint);
        }
        //竖线
        canvas.drawLine(mTimeTextWidth, mCurrentOrigin.y, mTimeTextWidth + 1, 48 * mHourHeight + mHeaderHeight, TimeRightLinePaint);
        /**
         * 绘制医生的名字
         */
        for (int i = 0; i < mDoctorSize; i++) {
            //  String name = "O(∩_∩)O~" + i;
            String name = dayCalendarBean.Items.get(i).DoctorName;
            float left = mTimeTextWidth + ((mWidthPerDoctor - (name.length() * 22)) / 2) + mWidthPerDoctor * i + mCurrentOrigin.x;
            canvas.drawText(name, left, 56 + mCurrentOrigin.y, mTimeTextPaint);
        }
        /**
         * 绘制时间刻度
         */
        timelist = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        int index = 0;
        while (index < 24) {
            calendar.set(01, 1, 1, index, 0, 0);
            Date d = calendar.getTime();
            calendar.add(Calendar.MINUTE, 30);
            Date d30 = calendar.getTime();
            SimpleDateFormat myFmt = new SimpleDateFormat("HH:mm");
            timelist.add(myFmt.format(d));
            timelist.add(myFmt.format(d30));
            index++;
        }
        for (int i = 0; i < timelist.size(); i++) {
            float top = mTimeTextWidth + mTimeTextHeight * i + mTimeTextSize / 2 + mTimeTextHeight + mCurrentOrigin.y;
            float linetop = mTimeTextWidth + mTimeTextHeight * i + mTimeTextHeight + mCurrentOrigin.y;
            String time = timelist.get(i);
            if (time == null)
                throw new IllegalStateException("A DateTimeInterpreter must not return null time");
            if (top < getHeight())
            /**
             * 第一个是字体
             * 第二个是宽度
             * 第三个是高度
             * 第四个是画笔
             */
                canvas.drawText(time, 16, top, mTimeTextPaint);

            /**
             * 横线
             */
            canvas.drawLine(mTimeTextWidth, linetop, getWidth(), linetop + 1, TimeRightLinePaint);
//            canvas.drawRect(mTimeTextWidth + mCurrentOrigin.x,
//                    mTimeTextWidth + mTimeTextSize / 2 + mTimeTextHeight + mCurrentOrigin.y,
//                    mTimeTextWidth + mWidthPerDoctor + mCurrentOrigin.x,
//                    mTimeTextWidth + mTimeTextSize / 2 + mTimeTextHeight + mHourHeight + mCurrentOrigin.y, mTimeTextPaint);

        }
        /**
         * 画最后一条横线
         */
        canvas.drawLine(mTimeTextWidth, mTimeTextWidth + mTimeTextHeight * 48 + mTimeTextHeight + mCurrentOrigin.y,
                getWidth(), mTimeTextWidth + mTimeTextHeight * 48 + mTimeTextHeight + mCurrentOrigin.y + 1, TimeRightLinePaint);
//        /**
//         * 绘制显示的区域
//         */
//        canvas.clipRect(mHeaderHeight, 0, mDoctorSize * mWidthPerDoctor + mHeaderHeight, mHeaderHeight, Region.Op.REPLACE);

    }

    /**
     * 到达最近得起源位置
     */
    private void goToNearestOrigin() {
        double leftDoctor = mCurrentOrigin.x / (mWidthPerDoctor);
        if (mCurrentFlingDirection != Direction.NONE) {
            leftDoctor = Math.round(leftDoctor);
        } else if (mCurrentScrollDirection == Direction.LEFT) {
            leftDoctor = Math.floor(leftDoctor);
        } else if (mCurrentScrollDirection == Direction.RIGHT) {
            leftDoctor = Math.ceil(leftDoctor);
        } else {
            leftDoctor = Math.round(leftDoctor);
        }
        int nearestOrigin = (int) (mCurrentOrigin.x - leftDoctor * (mWidthPerDoctor));

        if (nearestOrigin != 0) {
            // 停止滚动动画
            mScroller.forceFinished(true);
            mScroller.startScroll((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, -nearestOrigin, 0, (int) (Math.abs(nearestOrigin) / mWidthPerDoctor * mScrollDuration));
            ViewCompat.postInvalidateOnAnimation(DayCalendarView.this);
        }
        // 重置所有的状态
        mCurrentScrollDirection = mCurrentFlingDirection = Direction.NONE;
    }

    /**
     * 设置数据源
     */
    public void setData(DayCalendarBean dayCalendarBean) {
        this.dayCalendarBean = dayCalendarBean;
        this.mDoctorSize = dayCalendarBean.Items.size();
        postInvalidate();
    }

    /**
     * 比对两个事件是否重叠
     *
     * @param startDayCalendar 第一个事件
     * @param endDayCalendar   第二个事件
     * @return
     */
    public boolean isOverLap(DayCalendar startDayCalendar, DayCalendar endDayCalendar) {
        /**
         * 如果是开始时间一致的话,证明有重叠
         */
        if (DataUtil.getHourMinutes(startDayCalendar.StartTime).equals(DataUtil.getHourMinutes(endDayCalendar.StartTime))) {
            return true;
        }
        /**
         * 如果是结束时间一致的话,证明有重叠
         */
        if (DataUtil.getHourMinutes(startDayCalendar.EndTime).equals(DataUtil.getHourMinutes(endDayCalendar.EndTime))) {
            return true;
        }
        /**
         * 如果说第二个时间的开始时间早于第一个时间的结束时间,证明有重叠
         */
        if (Integer.parseInt(DataUtil.getHour(endDayCalendar.StartTime)) < Integer.parseInt(DataUtil.getHour(startDayCalendar.EndTime))) {
            return true;
        }

        if (Integer.parseInt(DataUtil.getHour(endDayCalendar.StartTime)) == Integer.parseInt(DataUtil.getHour(startDayCalendar.EndTime))) {
            if (Integer.parseInt(DataUtil.getMinutes(endDayCalendar.StartTime)) < Integer.parseInt(DataUtil.getMinutes(startDayCalendar.EndTime))) {
                return true;
            }
        }
        return false;

    }
}
